package com.homer.commons.sscpprotocol.server.impl;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

import com.homer.commons.sscpprotocol.server.base.AbstractMessage;
import com.homer.commons.sscpprotocol.server.servlet.SscpServletResponse;

public class SscpResponseImpl extends AbstractMessage implements
		SscpServletResponse {
	private static final long serialVersionUID = 7371210248110219946L;

	private byte sync_head = (byte) 0x5A;

	private byte key;
	private byte[] mainDeviceID;
	private byte[] slaveDevideID;

	private byte commandLength;
	private byte sync_end = (byte) 0xA5;

	private byte[] contentBytes = new byte[0];

	private Charset charset = Charset.defaultCharset();

	private ByteArrayOutputStream outputStream;

	private PrintWriter writer;

	private String errorMessage;

	public byte getSync_head() {
		return sync_head;
	}

	public byte getKey() {
		return key;
	}

	public void setKey(byte key) {
		this.key = key;
	}

	public byte[] getMainDeviceID() {
		return mainDeviceID;
	}

	public void setMainDeviceID(byte[] mainDeviceID) {
		this.mainDeviceID = mainDeviceID;
	}

	public byte[] getSlaveDevideID() {
		return slaveDevideID;
	}

	public void setSlaveDevideID(byte[] slaveDevideID) {
		this.slaveDevideID = slaveDevideID;
	}

	public byte getCommandLength() {
		return commandLength;
	}

	public void setCommandLength(byte commandLength) {
		this.commandLength = commandLength;
	}

	public byte getSync_end() {
		return sync_end;
	}

	public void setSync_end(byte sync_end) {
		this.sync_end = sync_end;
	}

	public void setSync_head(byte sync_head) {
		this.sync_head = sync_head;
	}

	public void setContent(byte[] content) {
		if (this.outputStream != null) {
			throw new IllegalStateException(
					"don't invoke setContentBytes after the outputStream/writer was create.");
		}
		this.contentBytes = content;
	}

	public void setContent(String body) {
		if (body == null)
			body = "";
		try {
			setContent(body.getBytes(this.charset.name()));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}

	public void setEncoding(String encoding) {
		this.charset = Charset.forName(encoding);
	}

	public String getEncoding() {
		return this.charset.name();
	}

	public synchronized OutputStream getOutputStream() {
		if (this.outputStream == null) {
			this.outputStream = new ByteArrayOutputStream(1024);
		}
		return this.outputStream;
	}

	public synchronized PrintWriter getPrintWriter() {
		if (this.writer == null) {
			OutputStreamWriter nestWriter = new OutputStreamWriter(
					getOutputStream(), this.charset);
			this.writer = new PrintWriter(nestWriter, true);
		}
		return this.writer;
	}

	public synchronized void clearBody() {
		if (this.contentBytes.length > 0) {
			this.contentBytes = new byte[0];
		}
		if (this.outputStream != null)
			this.outputStream.reset();
	}

	public synchronized byte[] getContentBytes() {
		if (this.errorMessage != null) {
			try {
				this.contentBytes = this.errorMessage.getBytes(this.charset
						.name());
			} catch (UnsupportedEncodingException e) {
				e.printStackTrace();
			}
		} else if (this.outputStream != null) {
			if (this.writer != null) {
				this.writer.flush();
			}
			this.contentBytes = this.outputStream.toByteArray();
		}
		return this.contentBytes;
	}

	public String getContentAsString() {
		String content = null;
		try {
			content = new String(getContentBytes(), this.charset.name());
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return content;
	}

	public String toString() {
		return "Sync_head=" + getSync_head() + "; commandLength="
				+ getCommandLength() + "; content=" + getContentAsString();
	}

	public void copyTo(SscpResponseImpl processedResponse) {
		processedResponse.setSync_head(getSync_head());
		processedResponse.setContent(getContentBytes());
		processedResponse.setEncoding(getEncoding());
		processedResponse.setSync_end(getSync_end());
		processedResponse.setMainDeviceID(getMainDeviceID());
		processedResponse.setSlaveDevideID(getSlaveDevideID());
		processedResponse.setKey(getKey());
		processedResponse.setCommandLength(getCommandLength());

	}

}
